class Promise {
    constructor(exectur) {
        this.PromiseState = 'pendding'
        this.PromiseResult = undefined
        const _this = this
        this.callbacks = []
        function resolve(data) {
            if (_this.PromiseState !== 'pendding') return
            _this.PromiseState = 'fulfilled'
            _this.PromiseResult = data
            setTimeout(() => {
                _this.callbacks.forEach((item) => {
                    item.onResolve(data)
                })
            })
        }
        function reject(data) {
            if (_this.PromiseState !== 'pendding') return
            _this.PromiseState = 'rejected'
            _this.PromiseResult = data

            setTimeout(() => {
                _this.callbacks.forEach((item) => {
                    item.onReject(data)
                })
            });
        }
        try {
            exectur(resolve, reject)
        } catch (error) {
            reject(error)
        }

    }
    then(onResolve, onReject) {
        const _this = this
        if (typeof onReject !== 'function') {
            onReject = reason => {
                throw reason
            }
        }
        if (typeof onResolve !== 'function') {
            onResolve = value => value
        }
        return new Promise((resolve, reject) => {
            function callback(type) {
                try {
                    let result = type(_this.PromiseResult)
                    if (result instanceof Promise) {
                        result.then(v => {
                            resolve(v)
                        }, r => {
                            reject(r)
                        })
                    } else {
                        resolve(result)
                    }
                } catch (error) {
                    reject(error)
                }
            }

            if (this.PromiseState === 'fulfilled') {
                setTimeout(() => {
                    callback(onResolve)
                });
            }
            if (this.PromiseState === 'rejected') {
                setTimeout(() => {
                    callback(onReject)
                });
            }
            if (this.PromiseState === 'pendding') {
                this.callbacks.push({
                    onResolve: function () {
                        callback(onResolve)
                    },
                    onReject: function () {
                        callback(onReject)
                    }

                })
            }
        })
    }
    catch(onReject) {
        return this.then(undefined, onReject)
    }

    static resolve(value) {
        return new Promise((resolve, reject) => {
            try {
                if (value instanceof Promise) {
                    value.then(v => {
                        resolve(v)
                    }, r => {
                        reject(r)
                    })
                } else {
                    resolve(value)
                }
            } catch (error) {
                reject(error)
            }
        })
    }
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }
    static all(promises) {
        return new Promise((resolve, reject) => {
            // 不要使用常量进行变量赋值,否则无效果且不报错。
            let count = 0
            let arr = []
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    count++
                    arr[i] = v
                    if (count === promises.length) {
                        resolve(arr)
                    }
                }, r => {
                    reject(r)
                })
            }
        })
    }
    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    resolve(v)
                }, r => {
                    reject(r)
                })
            }
        })
    }

}

export default Promise
